home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 326-350 / disk_348 / ilbmlib / play8svx.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  401 lines

  1. /* Ilbm.library C application, Play8SVX.c:
  2.  
  3.     Set your editor's TAB width to 3
  4.  
  5.     cc +p Play8SVX.c
  6.     as -cd IlbmInterface.asm
  7.     ln Play8SVX.o IlbmInterface.o -lcl32
  8.  
  9.     This program can only be run from the CLI. It takes 1 arg, the name of a
  10. file. If an 8SVX file, this program will then play the sample.
  11.  
  12. This is an example of using the library's mid-level routine LoadIFF() with
  13. our own FORM and PROP handlers instead of lib's default routines. This is the
  14. way to go if you need some non-ILBM reader/writer. Note that we need to
  15. define some PropFrame for 8SVX PROPs.
  16. */
  17.  
  18. #include "math.h"
  19. #include "functions.h"      /* Manx C declarations */
  20.  
  21. #include "exec/tasks.h"
  22. #include "exec/types.h"
  23. #include "exec/memory.h"
  24. #include "libraries/dos.h"
  25. #include "libraries/dosextens.h"
  26. #include "devices/audio.h"
  27.  
  28. /* The ilbm lib C INCLUDE file */
  29. #include "ILBM_Lib.h"
  30.  
  31.  
  32. /*-------------------------------defines---------------------------------*/
  33.  
  34. IFFP myForm();
  35. IFFP myProp();
  36.  
  37. typedef struct {
  38.     ULONG    oneShotHiSamples,
  39.     repeatHiSamples,
  40.     samplesPerHiCycle;
  41.     UWORD    samplesPerSec;
  42.     UBYTE    ctOctave,
  43.     sCompression;
  44.     LONG    volume;
  45.     } Voice8Header;
  46.  
  47.  /* Data for the Dissidents ILBM library */
  48. struct ILBMBase    *ILBMBase=0L;
  49.  
  50.  /* OK. Let's make up an 8SVXFrame and 8SVXPropFrame */
  51.  
  52. typedef struct {
  53.     USHORT        vFlags;
  54.     Voice8Header vhdr;
  55.     } v8SVXFrame;
  56.  
  57. typedef struct {
  58.    ULONG        NextPropFrame;
  59.     LONG        ifID;
  60.     UWORD        PropFrameSize;
  61.     v8SVXFrame PropFrame;
  62.     } v8SVXPropFrame;
  63.  
  64.     /* definitions for iFlags field */
  65. #define    VHDRFLAG    1    /* if a VHDR chunk found in the file */
  66.  
  67. #define GetVHDR(context, vhdr)  \
  68.     IFFReadBytes(sizeof(Voice8Header), context, (BYTE *)vhdr)
  69.  
  70. #define    ID_VHDR    MakeID('V','H','D','R')
  71. #define    ID_8SVX    MakeID('8','S','V','X')
  72.  
  73. v8SVXFrame        my8SVXFrame;
  74.  
  75.  /* Data for our program */
  76. struct FileHandle        *fp = 0;
  77. BYTE                        *memptr = 0;
  78. ULONG                        memsize = 0;
  79.  
  80. #define SetFlag(v,f)            ((v)|=(f))
  81. #define ClearFlag(v,f)        ((v)&=~(f))
  82. #define ToggleFlag(v,f)        ((v)^=(f))
  83. #define FlagIsSet(v,f)        ((BOOL)(((v)&(f))!=0))
  84.  
  85. /*=================== For audio.device playback of wave ==================*/
  86. struct IOAudio ioaudio = {0}, ioaudio2 = {0};
  87. struct MsgPort *audPort = 0L;
  88. UBYTE  audio_gub = 0;
  89. UBYTE  anychan[4] = {1,2,4,8};
  90.  
  91.  
  92. /*-----------closes audio dev, audio port, ILBM lib---------*/
  93.  
  94. VOID exit_all()
  95. {
  96.     if( audio_gub )    CloseDevice( &ioaudio );
  97.     if( audPort )        DeletePort( audPort );
  98.     if( ILBMBase )     CloseLibrary( ILBMBase );
  99.     exit( FALSE );
  100. }
  101.  
  102.  
  103. /*---------- Opens audio dev, audio port, ilbm lib ---------*/
  104.  
  105. VOID open_all()
  106. {
  107.  
  108.  /* Open the ILBM lib */
  109.     if( !(ILBMBase=(struct ILBMBase *)OpenLibrary("ilbm.library", 0L)) )
  110.     {
  111.         printf("Need the dissidents ilbm.library on boot disk\n");
  112.         exit();
  113.     }
  114.  
  115. /* Open audio.device and allocate a channel */
  116.  
  117.     if( !(audPort = CreatePort( "SAMP_Port", 0 )) )
  118.     {
  119.         puts("no audio port");
  120.         exit_all();
  121.     }
  122.  
  123.     ioaudio.ioa_Request.io_Message.mn_ReplyPort = audPort;
  124.  
  125.     ioaudio.ioa_Request.io_Command = ADCMD_ALLOCATE;
  126.     ioaudio.ioa_Data = (UBYTE *)anychan;
  127.     ioaudio.ioa_Length = 4;
  128.     ioaudio.ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK;
  129.     if( OpenDevice("audio.device", 0, &ioaudio, 0 ) )
  130.     {
  131.         puts("audio device open error\n");
  132.         exit_all();
  133.     }
  134.  
  135.     if( !(ioaudio.ioa_Request.io_Flags & IOF_QUICK ) )
  136.         GetMsg( audPort );
  137.  
  138.     audio_gub = 1;
  139.     
  140.     ioaudio2 = ioaudio;
  141.     /* initialize the AudioIO for the looping portion */
  142.  
  143. }
  144.  
  145.  
  146. /*----------------------------start of main()----------------------------*/
  147.  
  148. main( argc, argv )
  149. LONG argc;
  150. UBYTE *argv[];
  151. {
  152.     IFFP  Result;
  153.     LONG    err;
  154.  
  155.  /* LoadIFF() needs a Vectors structure */
  156.     Vectors myVectors;
  157.  
  158.  /* We expect the filename for the first arg. */
  159.     if( argc != 2 )
  160.     {
  161.         printf("USAGE: Play8SVX filename\n");
  162.         exit();
  163.     }
  164.  
  165.  /* Open ilbm.library, setup audio device */
  166.     open_all();
  167.  
  168.  /* Open the IFF File */
  169.     fp = Open( argv[1], MODE_OLDFILE );
  170.  
  171.     if (fp)
  172.     {
  173.  
  174.  /* Note that we are using the lib's middle level functions so that we can
  175.      install our own handlers for each encountered group and context. Also,
  176.      we can parse any IFF FORM, not just ILBMs and ANIMs using this level.
  177.      We are going to install our own function, myForm(), as the routine
  178.      which the library calls whenever it encounters a FORM ID. Our function,
  179.      myProp() will be called for 8SVX PROPS.
  180.      We "install" these routines by setting up the appropriate fields in our
  181.      Vectors structure. Let's do all this now. */
  182.  
  183.         myVectors.PROPhandler = myProp;
  184.         myVectors.FORMhandler = myForm;
  185.         myVectors.CHUNKhandler = 0;
  186.         myVectors.NonILBMhandler = 0;
  187.         /* Don't care about CHUNKhandler or NonILBMhandler as long as we have
  188.             our own FORMhandler. */
  189.  
  190.         /* Start parsing the file using LoadIFF() */
  191.         Result=LoadIFF( fp, &myVectors, &my8SVXFrame );
  192.  
  193.         /* O.K. we're back. Did we successfully parse as much as we wanted?
  194.             Well, our FORM routine should have returned IFF_DONE if we found
  195.             the 8SVX BODY. Otherwise, myForm, myProp, or an internal library
  196.             routine knocked us out by returning some other IFFP error code. Let's
  197.             get an informative error msg to display.
  198.         */
  199.  
  200.          /* If some error, get the IFFP error message and print it */
  201.         if( Result != IFF_DONE )
  202.         {
  203.             puts( GetIFFPMsg( Result ) );
  204.         }
  205.         else
  206.         {
  207.             /* Play one lousy, stinking note. Hey this is just for a test! */
  208.  
  209.             ioaudio.ioa_Volume = 64;    /* Play everything with MAX volume */
  210.             ioaudio2.ioa_Volume = 64;
  211.             ioaudio.ioa_Request.io_Command = CMD_WRITE;
  212.             ioaudio2.ioa_Request.io_Command = CMD_WRITE;
  213.  
  214.             /* Play the OneShot portion */
  215.             ioaudio.ioa_Data = (UBYTE *)memptr;
  216.             ioaudio.ioa_Length = (ULONG)my8SVXFrame.vhdr.oneShotHiSamples;
  217.             ioaudio.ioa_Request.io_Flags = ADIOF_PERVOL;
  218.             ioaudio.ioa_Cycles = 1;
  219.             if (my8SVXFrame.vhdr.samplesPerSec==0)
  220.                 my8SVXFrame.vhdr.samplesPerSec = 7000;
  221.             ioaudio.ioa_Period = 3579545L / my8SVXFrame.vhdr.samplesPerSec;
  222.  
  223.             ioaudio2.ioa_Data = (UBYTE *)(memptr + my8SVXFrame.vhdr.oneShotHiSamples);
  224.             ioaudio2.ioa_Request.io_Flags = 0;
  225.             ioaudio2.ioa_Cycles = 10;        /* only play the loop 10 times. */
  226.             ioaudio2.ioa_Period = ioaudio.ioa_Period;
  227.             ioaudio2.ioa_Length = (ULONG)my8SVXFrame.vhdr.repeatHiSamples;
  228.  
  229.             BeginIO( &ioaudio );
  230.  
  231.             if( ioaudio2.ioa_Length ) 
  232.                     BeginIO( &ioaudio2 );
  233.             err = WaitIO( &ioaudio );
  234.             GetMsg( audPort );
  235.             if(ioaudio2.ioa_Length)
  236.             {
  237.                 err = WaitIO( &ioaudio2 );
  238.                 GetMsg( audPort );
  239.             }
  240.  
  241.         }
  242.  
  243.         /* Close the IFF File */
  244.         Close(fp);
  245.  
  246.         /* Free any allocated CHIP mem for the sample */
  247.         if (memptr)  FreeMem(memptr, memsize);
  248.  
  249.     }
  250.     else printf( "Couldn't open %s. \n", argv[1]);
  251.  
  252.     printf("\n");
  253.  
  254.     exit_all();
  255. }              /* end of main() */
  256.  
  257.  
  258.  
  259. /*========= LoadIFF() calls me when it finds a FORM ==========*/
  260.  
  261. IFFP  myForm( chunkID, context, vectors, frame, proplist )
  262. PROPList *proplist;
  263. v8SVXFrame *frame;  /* We expect an 8SVXFrame */
  264. Vectors *vectors;
  265. GroupContext *context;
  266. ID         chunkID;
  267. {
  268. register    IFFP   code = IFF_OKAY;  /* Assume that we skip the FORM */
  269. register    ULONG  propf;
  270.  
  271.     /* Is this an 8SVX? If not, skip any other FORM by returning IFF_OKAY */
  272.  
  273.     if (chunkID == ID_8SVX)
  274.     {
  275.  
  276.     /* OK. It's 8SVX. Now check to see if we have any 8SVX PROPS.
  277.         If so, copy over that PropFrame to our present 8SVXFrame. */
  278.  
  279.         propf = SearchPROP(chunkID, proplist);
  280.         if    (propf) CopyMem(propf, frame, sizeof(v8SVXFrame) );
  281.  
  282.         while ( code >= 0 )
  283.         {
  284.  
  285.             /* Read in the next chunk */
  286.             code = GetFChunkHdr(context);
  287.  
  288.             /* ================== VHDR ===================== */
  289.                 if( code == ID_VHDR )
  290.                 {
  291.  
  292.                     /* Load the VHDR into 8SVXFrame and set VHDR flag */
  293.  
  294.                     code = GetVHDR(context, &frame->vhdr);
  295.                     if( code == IFF_OKAY )
  296.                     {
  297.                         SetFlag(frame->vFlags, VHDRFLAG);
  298.                     }
  299.                 }    /* end of VHDR parse */
  300.  
  301.             /* ================== BODY ===================== */
  302.                 if( code == ID_BODY )
  303.                 {
  304.                 /* If we got an VHDR, start loading the samples into chip mem */
  305.                     if ( FlagIsSet(frame->vFlags, VHDRFLAG) );
  306.                     {
  307.                         ClearFlag(frame->vFlags, VHDRFLAG);
  308.                         code = IFF_NOMEM;            /* Assume error */
  309.                         if ( memptr ) FreeMem( memsize, memptr );
  310.                         memsize = ChunkMoreBytes(context);
  311.                         if ( (memptr = AllocMem(memsize, MEMF_CHIP)) );
  312.                             {
  313.                             code = IFFReadBytes(memsize, context, memptr);
  314.                             if( code == IFF_OKAY )    code = IFF_DONE; /* Stop the parsing and return this */
  315.                             }
  316.                     }
  317.                 }    /* end of BODY parse */
  318.  
  319.         }    /* end of while */
  320.  
  321.     } /* end of ID_8SVX */
  322.  
  323.     /*  Reasons for falling out:
  324.          1). We found and successfully loaded the BODY, returning IFF_DONE.
  325.          2). GetFChunkHdr returned END_MARK, meaning that we got to the end
  326.                 of our 8SVX without finding a BODY.
  327.          3). One of the lib routines returned some IFFP error. We simply
  328.                 return that error.
  329.          All 3 scenarios cause our parsing to stop. Note that if we never find
  330.          an 8SVX FORM in the file, the lib will eventually return us to main
  331.          with LoadIFF returning END_MARK.  Note: To change this routine so that
  332.          it continues parsing the rest of the file, eliminate the line:
  333.          if (code == IFF_OKAY) code = IFF_DONE;
  334.          Instead, when you get back to main, you can test memptr to see if any
  335.          8SVX file was loaded.  You might want to do this if you were going to
  336.          add parsing for ID_SMUS to this form handler, and didn't want to stop
  337.          until you parsed the entire file.
  338.     */
  339.  
  340.     return( code );
  341. }
  342.  
  343.  
  344. /*========= LoadIFF() calls me when it finds a PROP ==========*/
  345.  
  346. IFFP myProp( chunkID, propID, context, vectors, frame, proplist )
  347. PROPList *proplist;
  348. v8SVXFrame *frame;
  349. Vectors *vectors;
  350. GroupContext *context;
  351. ID   propID;
  352. ID   chunkID;
  353. {
  354. register    IFFP    code = IFF_OKAY;
  355. register    v8SVXFrame    *pframe;
  356.  
  357.     /* We only care about 8SVX PROPS. If PropID not 8SVX, immediately return
  358.         IFF_OKAY to skip.  Otherwise, we allocate an 8SVXPropFrame and parse
  359.         the PROP's chunks just like in the FORMhandler, storing info in
  360.         this new PropFrame. Later, in our FORMHandler, we search the PROPList
  361.         for the appropriate ID and retrieve the info. The library automatically
  362.         updates the PROPList when it gets to the end of an IFF group so that you
  363.         don't have to keep track of which level we're at and which PROPS affect
  364.         which chunks. Also, the library frees all PropFrames that we allocate
  365.         with GetPROPStruct() by the time we return to main. */
  366.  
  367.  
  368.     if ( propID == ID_8SVX )
  369.     {
  370.         /* Allocate an 8SVXPropFrame and link into PROPList */
  371.         code = IFF_NOMEM;
  372.         pframe = GetPROPStruct( sizeof(v8SVXPropFrame), propID, proplist );
  373.         if ( pframe )
  374.         {
  375.             code = IFF_OKAY;
  376.             while ( code >= 0 )
  377.             {
  378.                 /* Read in the next chunk */
  379.                 code = GetPChunkHdr(context);
  380.  
  381.                 /* ================== VHDR ===================== */
  382.                 if( code == ID_VHDR )
  383.                 {
  384.  
  385.                     /* Load the VHDR into 8SVXPropFrame and set VHDR flag */
  386.                     code = GetVHDR(context, &pframe->vhdr);
  387.                     if( code == IFF_OKAY )
  388.                     {
  389.                         SetFlag(frame->vFlags, VHDRFLAG);
  390.                     }
  391.                 }    /* end of VHDR parse */
  392.  
  393.             }    /* end of while */
  394.  
  395.         }
  396.     }
  397.  
  398.     return( code );
  399. }
  400.  
  401.